package com.vr.xuecheng.auth.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vr.xuecheng.auth.dto.AuthParamsDTO;
import com.vr.xuecheng.auth.dto.LoginUserDTO;
import com.vr.xuecheng.auth.dto.RegisterDTO;
import com.vr.xuecheng.auth.entity.Menu;
import com.vr.xuecheng.auth.entity.User;
import com.vr.xuecheng.auth.entity.UserRole;
import com.vr.xuecheng.auth.mapper.UserMapper;
import com.vr.xuecheng.auth.service.IAuthService;
import com.vr.xuecheng.auth.service.IUserRoleService;
import com.vr.xuecheng.auth.service.IUserService;
import com.vr.xuecheng.base.exception.XueChengPlusException;
import com.vr.xuecheng.feign.client.CheckCodeClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author hzh
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService, UserDetailsService {
    private final ApplicationContext applicationContext;
    private final UserMapper userMapper;
    private final IUserRoleService userRoleService;
    private final CheckCodeClient checkCodeClient;
    private final PasswordEncoder bycriptPasswordEncoder;


    /**
     * 重写这个方法让它查询数据库
     */
    @Override
    public UserDetails loadUserByUsername(String json) throws UsernameNotFoundException {
        // 强制刷新缓存
        // 拿到username里的json信息，按道理这里只有username，但我把其他信息变成一个json串，作为username
        AuthParamsDTO authParamsDTO;
        authParamsDTO = JSON.parseObject(json, AuthParamsDTO.class);
        // 根据authType:获取对应的bean,从而执行不同的策略
        String beanName = authParamsDTO.getAuthType() + "_authService";
        IAuthService authBean = applicationContext.getBean(beanName, IAuthService.class);
        // 认证
        LoginUserDTO loginUserDTO = authBean.execute(authParamsDTO);
        // 获取用户权限
        List<Menu> menuList = userMapper.getPermissionByUserId(loginUserDTO.getId());
        // 封装结果
        return this.buildResult(loginUserDTO, menuList);
    }

    private UserDetails buildResult(LoginUserDTO loginUserDTO, List<Menu> menuList) {
        // 需要password进行认证
        String password = loginUserDTO.getPassword();
        List<String> permissions = menuList.parallelStream().map(Menu::getCode).toList();
        loginUserDTO.setPermissions(permissions);
        // 密码是私密内容置为null
        loginUserDTO.setPassword(null);
        String json = JSON.toJSONString(loginUserDTO);
        return org.springframework.security.core.userdetails.User.builder()
                .username(json)
                .password(password)
                .authorities(loginUserDTO.getAuthorities())
                .build();
    }

    @Override
    @Transactional
    public void register(RegisterDTO registerDTO) {
        // 校验验证码
        Boolean isVerify = checkCodeClient.verify(registerDTO.getCheckcodekey(), registerDTO.getCheckcode());
        if (!isVerify) {
            XueChengPlusException.cast("验证码错误");
        }
        // 查询用户是否已经注册了
        User userByUserName = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, registerDTO.getUsername())
        );
        User userByCellphone = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getCellphone, registerDTO.getCellphone())
        );
        if (userByUserName!=null) {
            XueChengPlusException.cast("用户名已经注册");
        }
        if (userByCellphone!=null) {
            XueChengPlusException.cast("手机号已经注册");
        }
        // 插入用户信息
        String id = UUID.randomUUID().toString();
        User waitRegisterUser = User.builder()
                .id(id)
                .username(registerDTO.getUsername())
                .password(bycriptPasswordEncoder.encode(registerDTO.getPassword()))
                .cellphone(registerDTO.getCellphone())
                .nickname(registerDTO.getNickname())
                .name(registerDTO.getUsername())
                .email(registerDTO.getEmail())
                .utype("101001")
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .status("1")
                .build();
        userMapper.insert(waitRegisterUser);
        // 分配角色
        userRoleService.save(UserRole.builder()
                .id(UUID.randomUUID().toString())
                .userId(id)
                // 学生角色
                .roleId("17")
                .build());
    }
}
